package com.turnos.gestion.atencion;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zul.Column;
import org.zkoss.zul.Columns;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.Row;
import org.zkoss.zul.Rows;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

import com.coreweb.componente.BodyPopupAceptarCancelar;
import com.coreweb.componente.ViewPdf;
import com.coreweb.componente.WindowPopup;
import com.coreweb.control.SimpleViewModel;
import com.coreweb.util.Misc;
import com.coreweb.util.MyArray;
import com.coreweb.util.MyPair;
import com.turnos.Configuracion;
import com.turnos.UtilDTO;
import com.turnos.control.cola.ControlCola;
import com.turnos.domain.Operador;
import com.turnos.domain.RegisterDomain;
import com.turnos.gestion.administracion.OperadorAssembler;
import com.turnos.gestion.administracion.OperadorDTO;
import com.turnos.gestion.panel.TareaDTO;
import com.turnos.gestion.panel.TurnoDTO;

public class AtencionViewModel extends SimpleViewModel {

	UtilDTO dtoUtil = (UtilDTO) this.getDtoUtil();

	List<OperadorDTO> operadores = new ArrayList<OperadorDTO>();

	private int nCol = 5;
	private Object[] opera = new Object[nCol];

	private List<OperadorDTO> operadores_c1 = new ArrayList<OperadorDTO>();
	private List<OperadorDTO> operadores_c2 = new ArrayList<OperadorDTO>();
	private OperadorDTO selectedOperador;
	private boolean operadorAutenticado = false;
	private boolean estadoLibre = false;
	private boolean estadoAtendiendo = false;
	private boolean estadoFds = false;
	private TareaDTO tareaActual = new TareaDTO();
	List<MyArray> servicios = new ArrayList<MyArray>();

	Misc misc = new Misc();
	ControlCola cc = new ControlCola(null);

	private TurnoDTO selectedTurno;
	private MyPair selectedTareaFds;
	private String observacion = "";
	private MyArray selectedServicioDerivado;

	@Init(superclass = true)
	public void init() {
		// System.out.println("============= Entro al init() ===========");
		try {
			this.distribuirOperadores();
			this.estadoAtendiendo = false;
			this.estadoLibre = false;
			this.estadoFds = false;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@AfterCompose(superclass = true)
	public void afterCompose() {
		// System.out.println("============= Entro al afterCompose() ===========");
	}

	public List<OperadorDTO> getOperadores() {
		return operadores;
	}

	public void setOperadores(List<OperadorDTO> operadores) {
		this.operadores = operadores;
	}

	public List<OperadorDTO> getOperadores_c1() {
		return operadores_c1;
	}

	public void setOperadores_c1(List<OperadorDTO> operadores_c1) {
		this.operadores_c1 = operadores_c1;
	}

	public List<OperadorDTO> getOperadores_c2() {
		return operadores_c2;
	}

	public void setOperadores_c2(List<OperadorDTO> operadores_c2) {
		this.operadores_c2 = operadores_c2;
	}

	public OperadorDTO getSelectedOperador() {
		return selectedOperador;
	}

	public void setSelectedOperador(OperadorDTO selectedOperador) {
		this.selectedOperador = selectedOperador;
	}

	public boolean isOperadorAutenticado() {
		return operadorAutenticado;
	}

	public void setOperadorAutenticado(boolean operadorAutenticado) {
		this.operadorAutenticado = operadorAutenticado;
	}

	public boolean isEstadoLibre() {
		return estadoLibre;
	}

	public void setEstadoLibre(boolean estadoLibre) {
		this.estadoLibre = estadoLibre;
	}

	public boolean isEstadoAtendiendo() {
		return estadoAtendiendo;
	}

	public void setEstadoAtendiendo(boolean estadoAtendiendo) {
		this.estadoAtendiendo = estadoAtendiendo;
	}

	public boolean isEstadoFds() {
		return estadoFds;
	}

	public void setEstadoFds(boolean estadoFds) {
		this.estadoFds = estadoFds;
	}

	public List<MyArray> getServicios() {
		return servicios;
	}

	public void setServicios(List<MyArray> servicios) {
		this.servicios = servicios;
	}

	public TareaDTO getTareaActual() {
		return tareaActual;
	}

	public void setTareaActual(TareaDTO tareaActual) {
		this.tareaActual = tareaActual;
	}

	public Object[] getOpera() {
		return opera;
	}

	public void setOpera(Object[] opera) {
		this.opera = opera;
	}

	public TurnoDTO getSelectedTurno() {
		return selectedTurno;
	}

	public void setSelectedTurno(TurnoDTO selectedTurno) {
		this.selectedTurno = selectedTurno;
	}

	public MyPair getSelectedTareaFds() {
		return selectedTareaFds;
	}

	public void setSelectedTareaFds(MyPair selectedTareaFds) {
		this.selectedTareaFds = selectedTareaFds;
	}

	public String getObservacion() {
		return observacion;
	}

	public void setObservacion(String observacion) {
		this.observacion = observacion;
	}

	public MyArray getSelectedServicioDerivado() {
		return selectedServicioDerivado;
	}

	public void setSelectedServicioDerivado(MyArray selectedServicioDerivado) {
		this.selectedServicioDerivado = selectedServicioDerivado;
	}

	/********************* OPERADORES EN DOS COLUMNAS *********************/

	private void distribuirOperadores() throws Exception {
		// System.out.println("========= Entro a distribuir operadores");
		List<OperadorDTO> ope = new ArrayList<OperadorDTO>();
		ope = this.cargarOperadores();

		for (int i = 0; i < nCol; i++) {
			this.opera[i] = new ArrayList<>();
		}

		int ff = 0;
		int cc = 0;
		for (int i = 0; i < ope.size(); i++) {
			List l = (List) this.opera[cc];
			l.add(ope.get(i));
			cc++;
			if (cc == nCol) {
				cc = 0;
				ff++;
			}
		}

		/*
		 * for (int i = 0; i < ope.size(); i++) { if (m.esPar(i) == true) {
		 * this.operadores_c2.add(ope.get(i)); } else {
		 * this.operadores_c1.add(ope.get(i)); } }
		 */
	}

	/*********************************************************************/

	public List<OperadorDTO> cargarOperadores() throws Exception {
		RegisterDomain rr = RegisterDomain.getInstance();
		List<Operador> operarios = rr.getAllOperarios();
		OperadorAssembler as = new OperadorAssembler();
		List<OperadorDTO> operadores = new ArrayList<OperadorDTO>();
		for (Operador operario : operarios) {
			operadores.add((OperadorDTO) as.domainToDto(operario));
		}
		return operadores;
	}
	
	/**
	 * Control de acceso del operador..
	 */
	
	private OperadorDTO oper;
	private String user = "";
	private String pass = "";
	private Window popup;
	
	@Command @NotifyChange("*")
	public void abrirPopUpContra(@BindingParam("d") OperadorDTO d) throws Exception {
		
		this.oper = d;
		this.setUser(d.getUsuario());
				
		popup = (Window) Executions.createComponents(Configuracion.AUTENTICAR_OPERADOR_ZUL, 
				this.mainComponent, null);
		popup.doModal();
		/*try {
			
			OperadorDTO dato = new OperadorDTO();
			dato.setUsuario(d.getUsuario());
			dato.setNombre(d.getNombre());
			WindowPopup w = new WindowPopup();
			w.setModo(WindowPopup.NUEVO);
			w.setTitulo("Autenticar Operador");
			w.setWidth("300px");
			w.setHigth("200px");
			w.setDato(dato);
			w.show(Configuracion.AUTENTICAR_OPERADOR_ZUL);
			if (w.isClickAceptar()) {
				OperadorDTO datoFinal = (OperadorDTO) w.getDato();
				String pass = misc.encriptar(datoFinal.getPass());
				if (pass.compareTo(d.getPass()) == 0) {
					this.operadorAutenticado = true;
					this.selectedOperador = d;
					this.setearEstado();
				} else {
					String mensaje = "Contrasenha incorrecta. No se ha podido autenticar al operador.";
					this.mensajeError(mensaje);
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	@Command @NotifyChange("*")
	public void validarAcceso(@BindingParam("cmp") Textbox cmp){
		String pass = misc.encriptar(this.pass);
		if (pass.compareTo(this.oper.getPass()) == 0) {
			this.operadorAutenticado = true;
			this.selectedOperador = this.oper;
			this.setearEstado();
			this.popup.detach();
			this.user = "";
			this.pass = "";
		} else {
			String mensaje = "Contraseña incorrecta";
			cmp.setStyle("border-color:red");
			this.m.mensajePopupTemporal(mensaje, "error", cmp);
		}
	}
	
	@Command @NotifyChange("*")
	public void cancelarAcceso(){
		this.oper = new OperadorDTO();
		this.pass = "";
		this.user = "";
		this.popup.detach();
	}

	private String obsvCancelacion = "";
	private MyArray selectedPuesto;

	public String getObsvCancelacion() {
		return obsvCancelacion;
	}

	public void setObsvCancelacion(String obsvCancelacion) {
		this.obsvCancelacion = obsvCancelacion;
	}

	public MyArray getSelectedPuesto() {
		return selectedPuesto;
	}

	public void setSelectedPuesto(MyArray selectedPuesto) {
		this.selectedPuesto = selectedPuesto;
	}

	@Command
	@NotifyChange("*")
	public void abrirPopUpSeleccionarTurno() {
		try {
			/** Crea el PopUp para la seleccion del turno **/

			WindowPopup w = new WindowPopup();
			w.setModo(WindowPopup.NUEVO);
			w.setTitulo("Seleccionar Turno");
			w.setWidth("900px");
			w.setHigth("450px");
			w.setDato(this);
			w.show(Configuracion.SELECCIONAR_TURNO_ZUL);

			if (w.isClickAceptar()) {

				if (cc.bloquearTurno(this.selectedTurno) != null) { // Trata de
																	// bloquear
																	// el turno
					/** Crea el WindowPopUp para las operaciones del turno **/
					OperacionesTurnoControlNuevo wp = new OperacionesTurnoControlNuevo();
					wp.show(WindowPopup.NUEVO, wp, this.selectedTurno,
							this.selectedOperador);

					
					if (wp.isClickAceptar() == false) {
						/** Caso2: Hizo click en el boton cancelar **/
						cc.desbloquearTurno(this.selectedTurno);
						this.mensajePopupTemporal("No se realizó ninguna operación.");

					} else {

						/** Caso1: Hizo click en el boton Aceptar **/
						long estadoAtendiendo = this.dtoUtil
								.getEstadoAtendiendo().getId();
						long estadoEsperando = this.dtoUtil
								.getEstadoEsperando().getId();
						long estadoLlamando = this.dtoUtil.getEstadoLlamando()
								.getId();
						long estadoCancelado = this.dtoUtil
								.getEstadoCancelado().getId();

						
						long estadoTurno = this.selectedTurno.getEstado()
								.getId();
						String mensaje = "";

						if (estadoTurno == estadoLlamando) {
							cc.llamarTurnoLuego(this.selectedTurno);
							mensaje = "Se ha llamado al turno "
									+ this.selectedTurno.getNumero();

						} else if (estadoTurno == estadoAtendiendo) {
							cc.atenderTurno(this.selectedTurno,
									this.selectedOperador,
									wp.getSelectedPuesto());
							mensaje = "Se ha iniciado la atención del turno "
									+ this.selectedTurno.getNumero();

						} else if (estadoTurno == estadoCancelado) {
							// obtiene la observacion
							this.setObsvCancelacion(wp.getObservacion());
							cc.cancelarTurno(this.selectedTurno,
									this.obsvCancelacion);
							mensaje = "Se ha cancelado el turno "
									+ this.selectedTurno.getNumero();
						} else if (estadoTurno == estadoEsperando) {
							cc.llamarTurnoLuego(this.selectedTurno);
							mensaje = "Llamar luego al turno "
									+ this.selectedTurno.getNumero();
						} else {
							/** No hubieron cambios, desbloquear el turno **/
							mensaje = "No se realizó ninguna operación.";
							cc.desbloquearTurno(this.selectedTurno);
						}
						this.mensajePopupTemporal(mensaje, 5000);

					}
					this.setearEstado();
					this.operadorAutenticado = false;
				} else { // Si no puede bloquear retorna un mensaje
					this.mensajePopupTemporalWarning("El turno ya ha sido bloqueado por otro operador.");
				}

			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Command
	@NotifyChange("*")
	public void abrirPopUpDerivar() {
		try {
			WindowPopup w = new WindowPopup();
			w.setModo(WindowPopup.NUEVO);
			w.setTitulo("Derivar Turno");
			w.setWidth("400px");
			w.setHigth("400px");
			w.setDato(this);
			w.show(Configuracion.DERIVAR_TURNO_ZUL);
			if (w.isClickAceptar()) {
				cc.cerrarTarea(this.tareaActual, this.selectedOperador);
				cc.derivarTurno(this.tareaActual.getTurno(),
						this.selectedServicioDerivado, this.selectedOperador);
				this.selectedOperador.setEstado(dtoUtil
						.getEstadoOperadorLibre());
				/* cc.cambiarAEstadoLibre(this.selectedOperador); */
				this.estadoAtendiendo = false;
				this.estadoLibre = true;
				String mensaje = "Se ha derivado el turno "
						+ this.tareaActual.getTurno().getNumero() + ".";
				this.mensajePopupTemporal(mensaje, 5000);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Command
	@NotifyChange("*")
	public void abrirPopUpFds() {
		try {
			WindowPopup w = new WindowPopup();
			w.setModo(WindowPopup.NUEVO);
			w.setTitulo("Tarea FDS");
			w.setWidth("300px");
			w.setHigth("400px");
			w.setDato(this);
			w.show(Configuracion.TAREA_FDS_ZUL);
			if (w.isClickAceptar()) {
				System.out.println("====== dato " + this.selectedTareaFds);
				String motivo = this.getMotivoAnulacion();
				this.cambiarEstadoToFds(this.selectedTareaFds, motivo);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setearEstado() {
//		System.out.println("========== Estado "
//				+ this.selectedOperador.getEstado().getSigla() + " "
//				+ this.selectedOperador.getEstado().getText());
		if (this.selectedOperador.getEstado().getText().compareTo("Libre") == 0) {
			this.estadoLibre = true;
			this.estadoAtendiendo = false;
			this.estadoFds = false;
		} else if (this.selectedOperador.getEstado().getText()
				.compareTo("Atendiendo") == 0) {
			this.estadoAtendiendo = true;
			this.estadoLibre = false;
			this.estadoFds = false;
			this.obtenerTareaActual();
		} else {
			this.estadoFds = true;
			this.estadoLibre = false;
			this.estadoAtendiendo = false;
		}
	}

	@Command
	@NotifyChange("*")
	public void cambiarEstadoToFds(MyPair tipoTareaFds, String motivo) {
		System.out.println("========== Cambiar estado a FDS "
				+ dtoUtil.getEstadoOperadorFds());
		this.selectedOperador.setEstado(dtoUtil.getEstadoOperadorFds());
		try {
			cc.cambiarAEstadoFds(this.selectedOperador, tipoTareaFds, motivo);
			this.estadoLibre = false;
			this.estadoFds = true;
			String mensaje = "El estado del operador "
					+ this.selectedOperador.getNombre() + " "
					+ " ha cambiado a Fuera de Servicio (FDS)";
			this.mensajePopupTemporal(mensaje, 5000);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Command
	@NotifyChange("*")
	public void cambiarEstadoToLibre() {
		System.out.println("========== Cambiar estado a libre "
				+ dtoUtil.getEstadoOperadorLibre());
		this.selectedOperador.setEstado(dtoUtil.getEstadoOperadorLibre());
		try {
			cc.cambiarAEstadoLibre(this.selectedOperador);
			this.estadoFds = false;
			this.estadoLibre = true;
			String mensaje = "El estado del operador "
					+ this.selectedOperador.getNombre() + " "
					+ " ha cambiado a Libre";
			this.mensajePopupTemporal(mensaje, 5000);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Command
	@NotifyChange("*")
	public void volverAlInicio() {
		this.operadorAutenticado = false;
	}

	public void obtenerTareaActual() {
		try {
			this.tareaActual = cc.getTareaCorrientePor(this.selectedOperador);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	List<MyArray> serviciosSeleccionados = new ArrayList<MyArray>();

	public List<MyArray> getServiciosSeleccionados() {
		return serviciosSeleccionados;
	}

	public void setServiciosSeleccionados(List<MyArray> serviciosSeleccionados) {
		this.serviciosSeleccionados = serviciosSeleccionados;
	}

	@Command
	@NotifyChange("*")
	public void terminarTurno() {
		System.out.println("========== Cambiar estado a libre "
				+ dtoUtil.getEstadoOperadorLibre());
		this.selectedOperador.setEstado(dtoUtil.getEstadoOperadorLibre());
		this.servicios = ((UtilDTO) this.getDtoUtil()).getServicios();
		try {
			RegisterDomain rr = RegisterDomain.getInstance();
			/* Mostrar y obtner los servicios adicionales realizados */
			WindowPopup w = new WindowPopup();
			w.setModo(WindowPopup.NUEVO);
			w.setTitulo("Seleccionar Servicios Adicionales");
			w.setWidth("400px");
			w.setHigth("600px");
			w.setDato(this);
			w.show(Configuracion.SERVICIOS_ADICIONALES_ZUL);
			if (w.isClickAceptar()) {
				// Obtener los servicios seleccionados
				List<MyArray> serviciosAdicionales = new ArrayList<MyArray>();
				String servAd = "";
				int total = this.serviciosSeleccionados.size();
				for (int i = 0; i < total; i++) {
					serviciosAdicionales
							.add(this.serviciosSeleccionados.get(i));
					servAd = servAd
							+ ((MyArray) this.serviciosSeleccionados.get(i))
									.getPos1();
					if (i < total - 1) {
						servAd = servAd + " - ";
					}
				}
				System.out
						.println("========= Servicios adicionales seleccionados "
								+ servAd);
				this.tareaActual.setServiciosAdicionales(servAd);
				this.tareaActual.setObservacion(this.observacion);
				cc.cerrarTarea(this.tareaActual, this.selectedOperador);

				this.estadoAtendiendo = false;
				this.estadoLibre = true;
				this.serviciosSeleccionados = new ArrayList<MyArray>();
				String mensaje = "Se ha finalizado la atención del turno "
						+ this.tareaActual.getTurno().getNumero() + ".";
				this.mensajePopupTemporal(mensaje, 5000);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/** Reporte para el operador dadas fechas de incio y fin **/

	@Command
	public void reporteOperador() throws Exception {

		Grid gd = new Grid();

		Columns cls = new Columns();
		cls.setParent(gd);

		Column cl = new Column();
		cl.setWidth("100px");
		cl.setParent(cls);

		Column cl2 = new Column();
		cl2.setParent(cls);

		Rows rws = new Rows();
		rws.setParent(gd);

		Row rw = new Row();
		rw.setParent(rws);

		Label lb = new Label();
		lb.setValue("Inicio:");
		lb.setParent(rw);

		Row rw2 = new Row();
		rw2.setParent(rws);

		Label lb2 = new Label();
		lb2.setValue("Fin:");
		lb2.setParent(rw2);

		Datebox ix = new Datebox();
		ix.setValue(this.m.getFechaHoy00());
		ix.setWidth("150px");
		ix.setReadonly(true);
		ix.setParent(rw);

		Datebox ix2 = new Datebox();
		ix2.setValue(this.m.getFechaHoy2359());
		ix2.setWidth("150px");
		ix2.setReadonly(true);
		ix2.setParent(rw2);

		BodyPopupAceptarCancelar b = new BodyPopupAceptarCancelar();
		b.addComponente("", gd);
		b.setHighWindows("200px");
		b.setWidthWindows("320px");
		b.showPopupUnaColumna("");

		if (b.isClickAceptar()) {
			System.out.println("============ Entro a generarReporte");
			Date fechaInicio = ix.getValue();
			Date fechaFin = ix2.getValue();
			this.generarReporte(fechaInicio, fechaFin);
		}

	}

	/**
	 * Genera el reporte del operador
	 * 
	 * @throws Exception
	 */
	public void generarReporte(Date fechaInicio, Date fechaFin)
			throws Exception {

		OperadorReporte r = new OperadorReporte();

		r.setInformacion(this.selectedOperador, fechaInicio, fechaFin);

		ViewPdf vp = new ViewPdf();
		vp.showReporte(r, this);
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	public OperadorDTO getOper() {
		return oper;
	}

	public void setOper(OperadorDTO oper) {
		this.oper = oper;
	}

}
